package org.sction.security.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class SecurityUrlFilter implements Filter {
	private static final Logger logger = Logger
			.getLogger(SecurityUrlFilter.class);
	static final long serialVersionUID = 1L;
	public ServletContext servletContext;
	protected FilterConfig filterConfig;
	protected String errorPage = "/error.jsp";
	protected int regexSize = 5;
	protected int mode = Pattern.CASE_INSENSITIVE;
	protected static List<FilterBean> regexList = new ArrayList<FilterBean>();

	public SecurityUrlFilter() {
		servletContext = null;
		filterConfig = null;
	}

	public static void add(FilterBean regex) {
		regexList.add(regex);
	}

	public static void remove(FilterBean regex) {
		for (FilterBean fb : regexList) {
			if (fb.getRegex().equals(regex.getRegex())) {
				regexList.remove(fb);
				break;
			}
		}
	}

	public static List<FilterBean> getRegexList() {
		return regexList;
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
		servletContext = filterConfig.getServletContext();
		try {
			regexSize = Integer.parseInt(filterConfig
					.getInitParameter("regexSize"));
		} catch (Exception e) {
			logger.error("regexSize的值必须为整数");
		}
		for (int i = 0; i <= regexSize; i++) {
			String regex = filterConfig.getInitParameter("regex" + i);
			if (regex != null && !regex.equals("")) {
				if (regex != null && !regex.equals("")) {
					String modestr = filterConfig.getInitParameter("errorPage"
							+ i);
					int modex = 2;
					if (modestr != null && !modestr.equals("")) {
						try {
							modex = Integer.parseInt(modestr);
						} catch (Exception e) {
							logger.error("mode[x]的值必须为整数");
						}
					}
					regexList.add(new FilterBean(regex, filterConfig
							.getInitParameter("errorPage" + i), modex));
				}
			}
		}

	}

	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		String path = request.getContextPath();
		String uri = request.getRequestURI();
		Enumeration<String> names = request.getParameterNames();
		uri += "?";
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String[] values = request.getParameterValues(name);
			if (values != null && values.length > 0) {
				for (int i = 0; i < values.length; i++) {
					String value = values[i];
					uri += name + "=" + value + "&";
				}
			}
		}
		uri = uri.substring(0, uri.length() - 1);
		for (FilterBean regex : regexList) {
			Pattern pattern = null;
			if (mode == -1) {
				pattern = Pattern.compile(regex.getRegex());
			} else {
				pattern = Pattern.compile(regex.getRegex(), mode);
			}
			Matcher m = pattern.matcher(uri);
			if (m.find()) {
				String page = regex.getErrorPage();
				if (page != null && !page.trim().equals("")
						&& !page.equalsIgnoreCase("null")) {
					page = path + page;
				} else {
					page = path + errorPage;
				}
				logger.info("请求：" + uri);
				logger.info("非法请求即将跳转到：" + page);
				request.getRequestDispatcher(page).forward(request, response);
				return;
			}
		}
		chain.doFilter(request, response);
	}

	public void destroy() {
		servletContext = null;
		filterConfig = null;
	}
}

class FilterBean {
	private String regex = "";
	private String errorPage = "";
	private int mode = Pattern.CASE_INSENSITIVE;

	public FilterBean(String regex, String errorPage, int mode) {
		this.regex = regex;
		this.errorPage = errorPage;
		this.mode = mode;
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	public String getErrorPage() {
		return errorPage;
	}

	public void setErrorPage(String errorPage) {
		this.errorPage = errorPage;
	}

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

}